﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Data
{
    static public class Universe
    {
        static private Dictionary<Guid, StarSystem> universe = new Dictionary<Guid, StarSystem>();

        static public StarSystem GetStarSystem(Guid id)
        {
            if (!universe.ContainsKey(id))
                return null;

            return universe[id];
        }

        static public Guid NewStarSystem(string name)
        {
            StarSystem star = new StarSystem { Name = name };
            universe.Add(star.StarId, star);

            return star.StarId;
        }

        static public int RangeTo(MapIndex sourceHex, MapIndex targetHex)
        {
            int deltaX = Math.Abs(sourceHex.X - targetHex.X);
//            int deltaY = Math.Abs(sourceHex.Y - targetHex.Y);

            // =IF(Sheet1!$A$4=EVEN(Sheet1!$A$4),Sheet1!$B$4-ROUNDDOWN(DeltaX/2,0),Sheet1!$B$4-ROUNDUP(DeltaX/2,0))
            // =IF(Sheet1!$A$4=EVEN(Sheet1!$A$4),Sheet1!$B$4+ROUNDUP(DeltaX/2,0),Sheet1!$B$4+ROUNDDOWN(DeltaX/2,0))
            int ya;
            int yb;
            if (sourceHex.X == Even(sourceHex.X))
            {
                ya = sourceHex.Y - (int)Math.Floor((double)(deltaX / 2));
                yb = sourceHex.Y + (int)Math.Ceiling((double)(deltaX / 2));
            }
            else
            {
                ya = sourceHex.Y - (int)Math.Ceiling((double)(deltaX / 2));
                yb = sourceHex.Y + (int)Math.Floor((double)(deltaX / 2));
            }

            // =IF(AND(Ya<=D4,D4<=Yb), DeltaX, DeltaX+MIN(ABS(D4-Ya),ABS(D4-Yb)))
            int result;

            if (ya <= targetHex.Y && targetHex.Y <= yb)
                result = deltaX;
            else
                result = deltaX + Math.Min(Math.Abs(targetHex.Y - ya), Math.Abs(targetHex.Y - yb));

            return result;
        }

        static private int Even(int value)
        {
            int v = Math.Abs(value);
            int r;
            if (Math.DivRem(v, 2, out r) != 0)
                v += 1;

            if (value < 0)
                v *= -1;

            return v;
        }

        static public Guid CreateStarSystem(string name)
        {
            Guid id = Universe.NewStarSystem(name);

            return id;
        }

        static public void LinkStarSystems(StarSystem star, params WarpPointInfo[] links)
        {
            foreach (WarpPointInfo info in links)
            {
                info.id = star.CreateWarpPoint(info.destination, info.location, info.name);
            }
        }
    }

    public class MapIndex
    {
        #region Attributes
        private int x;
        private int y;
        private Guid systemId;

        const int HEX_HIEGHT = 40;
        const int HEX_SIDE_WIDTH = 12;
        const int HEX_CENT_WIDTH = 24;
        const int HEX_COLUMN_WIDTH = HEX_CENT_WIDTH + HEX_SIDE_WIDTH;
        #endregion

        public MapIndex(Guid systemId, int x, int y)
        {
            this.systemId = systemId;
            this.x = x;
            this.y = y;
        }

        #region Properties
        public int X
        {
            get { return x; }
            set { x = value; }
        }

        public int Y
        {
            get { return y; }
            set { y = value; }
        }

        public int HexCoordX
        {
            get { return x * 2; }
        }

        public int HexCoordY
        {
            get
            {
                if (x % 2 == 0)
                    return y * 2;
                else
                    return (y * 2) - 1;
            }
        }

        public int ScreenX
        {
            get { return HEX_COLUMN_WIDTH * x; }
        }

        public int ScreenY
        {
            get
            {
                if (x % 2 == 0)
                    return HEX_HIEGHT * y;
                else
                    return (HEX_HIEGHT * y) - (HEX_HIEGHT / 2);
            }
        }

        public Guid SystemId
        {
            get { return systemId; }
            set { systemId = value; }
        }

        public override int GetHashCode()
        {
            return systemId.GetHashCode();
        }
        #endregion
    }
}
